#include "../头文件/ChargeFunction.h"

// 判断退出键是否点击
bool isExitKey = false;
// 判断各个窗口是否弹出
bool showWindow = false;
// 判断充电卡解锁功能是否点击
bool showChargingCardUnlock = false;
// 判断充电账号是否点击
bool showChargingAccount = false;
// 判断修改密码是否点击
bool isChangePassword = false;
// 判断充电卡功能是否点击
bool showChargeCard = false;
// 判断是否开始充电
bool isCharging = false;
/**
 * @brief 获取当前的日期时间字符串
 *
 * @return TextType 字符串首地址
 */
TextType getDate()
{
    time_t current_time;
    time(&current_time);

    // 将time_t转换为tm结构
    struct tm *time_info = localtime(&current_time);

    // 定义一个缓冲区来存储格式化后的时间字符串
    TextType time_string = (TextType)calloc(50, sizeof(char));

    if (time_string == NULL)
    {
        fprintf(stderr, "内存分配失败\n");
        return NULL;
    }

    // 使用strftime格式化时间
    strftime(time_string, 50, "%Y-%m-%d %H:%M:%S", time_info);

    return time_string;
}
/**
 * @brief 显示全功能界面
 *
 */
void functions()
{
    // 显示功能界面
    show_anyjpg(0, 0, FUNCTIONS_IMAGE);
    // 给当前日期分配内存空间(防止频繁创建释放内存)
    // 定义缓冲区
    TextType curdate = (TextType)calloc(50, sizeof(char));
    while (1)
    {

        // 搞一个点击事件函数
        Function Function_Flag = functions_click_event(false, curdate);
        switch (Function_Flag)
        {
        case SHOWEXIT:
            close_functions_window();
            // 弹出退出账号窗口
            show_anyjpg(0, 0, EXIT_IMAGE);
            isExitKey = true;
            break;
        case SHOW_CHARGE_CARD:
            show_charge_card();
            break;
        case SHOW_DEVICE_INFO:
            show_device_info();
            break;
        case SHOW_CHARGING_PRICE:
            show_charging_price();
            break;
        case SHOW_CHARGING_CARD_UNLOCK:
            show_charging_card_unlock();
            break;
        case UNLOCK_CONFIRM:
            unlock_card();
            close_functions_window();
            break;
        case UNLOCK_EXIT:
            close_functions_window();
            break;
        case SHOW_CHARGING_ACCOUNT:
            show_charging_account();
            break;
        case PASSWD:
            change_password();
            isChangePassword = false;
            close_functions_window();
            break;
        case RECHARGE:
            recharge();
            close_functions_window();
            break;
        case SHOW_CHARGING_FIND:
            show_charging_info();
            break;
        case SHOW_CHARGING_MODE:
            show_charge_mode();
            close_functions_window();
            break;
        default:
            break;
        }
        // 显示退出弹窗
        if (isExitKey && (Function_Flag == NOT_EXIT || Function_Flag == EXIT))
        {
            exit_account(Function_Flag);
            isExitKey = false;
        }

        // 设置一个退出界面的条件(退出账号)
        if (objectselection != USER)
            break;
        // functions_click_event(false,click_event_handler);
    }
}
/**
 * @brief 左上角显示当前登录账号
 *
 */
void show_current_account()
{
    // 初始化Lcd
    int *lcd_mmap = lcd_init_mmap();

    // 打开字体文件
    font *f = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");

    // 字体大小的设置
    fontSetSize(f, 24);

    // 创建两个画板（点阵图）
    // 账号画板
    bitmap *bm = createBitmapWithInit(110, 25, 4, getColor(255, 0, 0, 0)); // 也可使用createBitmapWithInit函数，改变画板颜色
                                                                           // bitmap *bm = createBitmap(288, 100, 4);

    // char buf[] = "创建一个画板32字体1大小的设置";

    // 将字体写到点阵图上

    fontPrint(f, bm, 0, 0, CurrentUser.Account, getColor(0, 0, 255, 0), 600);

    // 把字体框输出到LCD屏幕上
    show_font_to_lcd(lcd_mmap + 55 + 800 * 15, 0, 0, bm);
    // 关闭字体，关闭画板
    fontUnload(f);
    destroyBitmap(bm);
    lcd_close_mmap(lcd_mmap);
}
/**
 * @brief 功能界面中间顶部显示日期
 *
 */
void showdate(TextType curdate)
{
    // 初始化Lcd
    int *lcd_mmap = lcd_init_mmap();

    // 打开字体文件
    font *f = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");

    // 字体大小的设置
    fontSetSize(f, 24);

    // 创建两个画板（点阵图）
    // 账号画板
    bitmap *bm = createBitmapWithInit(180, 25, 4, getColor(255, 0, 0, 0)); // 也可使用createBitmapWithInit函数，改变画板颜色
                                                                           // bitmap *bm = createBitmap(288, 100, 4);

    // char buf[] = "创建一个画板32字体1大小的设置";

    // 将字体写到点阵图上

    fontPrint(f, bm, 0, 0, curdate, getColor(0, 0, 255, 0), 180);

    // 把字体框输出到LCD屏幕上
    show_font_to_lcd(lcd_mmap + 300 + 800 * 5, 0, 0, bm);
    // 关闭字体，关闭画板
    fontUnload(f);
    destroyBitmap(bm);
    lcd_close_mmap(lcd_mmap);
}
/**
 * @brief 从硬件读取时间更新日期
 *
 * @param time_string
 * @param size
 */
void updateDateFromSystem(TextType time_string, size_t size)
{
    time_t current_time;
    time(&current_time);

    // 将time_t转换为tm结构
    struct tm *time_info = localtime(&current_time);

    // 使用strftime格式化时间
    strftime(time_string, size, "%Y-%m-%d %H:%M:%S", time_info);
}
/**
 * @brief 退出账号
 *
 */
void exit_account(Function Function_Flag)
{
    // 如果退出
    if (Function_Flag == EXIT)
    {
        free_user_data(&CurrentUser);
        show_anyjpg(0, 0, EXIT_SUCCESS_IMAGE);
        sleep(1);
        show_object_select(OBJECT_SELECT_IMAGE);
    }
    // 取消的话
    else if (Function_Flag == NOT_EXIT)
        show_anyjpg(0, 0, FUNCTIONS_IMAGE);
}
/**
 * @brief 充电功能模块的点击事件
 *
 * @param BlockState 阻塞状态
 * @param curdate 当前日期
 * @return Function
 */
Function functions_click_event(bool BlockState, TextType curdate)
{
    int x = 0, y = 0;
    struct input_event input_info = {0};        // 保存触摸屏事件信息
    int fd = open("/dev/input/event0", O_RDWR); // 打开触摸屏文件
    while (1)
    {
        // 选择是否阻塞读取(阻塞的话 只能实现一个按键的点击)
        if (!BlockState)
        {
            // 设置为非阻塞 --begin--
            int status = fcntl(fd, F_GETFL);     // 1，获取当前的status 状态字
            status |= O_NONBLOCK;                // 2，将“非阻塞”属性加入status
            status = fcntl(fd, F_SETFL, status); // 3，将配置好的status 设置到fd 中
            // 设置完毕 --end--
        }

        ssize_t bytesRead = read(fd, &input_info, sizeof(input_info)); // 阻塞读取

        if (bytesRead == -1)
        {
            // 非阻塞读取，没有数据可读取
            if (errno == EAGAIN)
            {
                // 显示账号
                show_current_account();
                // 从硬件读取时间更新时间字符串
                updateDateFromSystem(curdate, 50);
                // 显示时间
                showdate(curdate);
                // 延时500毫秒
                usleep(500000);
                // 非阻塞读取，没有数据可读取
                x = y = 0;
                continue;
            }
            // 其他错误，退出循环
            else
                break;
        }
        // 手松开
        if (EV_KEY == input_info.type && BTN_TOUCH == input_info.code && 0 == input_info.value)
        {
            printf("手松开触摸屏\n");
            // break; // 手松开退出
        }
        // 触摸屏绝对位移，x轴坐标发生改变
        if (EV_ABS == input_info.type && ABS_X == input_info.code)
        {
            x = input_info.value * 0.78125; // 保存x轴坐标(这里把显示屏x坐标优化成800)
            // x = input_info.value ;
        }
        // 触摸屏绝对位移，y轴坐标发生改变
        if (EV_ABS == input_info.type && ABS_Y == input_info.code)
        {
            y = input_info.value * 0.8; // 保存y轴坐标(这里把显示屏y坐标优化成480)
            // y = input_info.value; // 保存y轴坐标(这里把显示屏y坐标优化成480)
        }
        printf("(%d, %d)\n", x, y);

        // 功能界面的点击(不显示退出账号界面时才可点击其他按键)
        // 显示退出账号界面
        if (!isExitKey && !showWindow && x >= 715 && x <= 795 && y >= 5 && y <= 45)
            return SHOWEXIT;
        // 取消退出键
        else if (!showWindow && isExitKey && x >= 306 && x <= 390 && y >= 285 && y <= 320)
            return NOT_EXIT;
        // 退出账号键
        else if (!showWindow && isExitKey && x >= 400 && x <= 484 && y >= 285 && y <= 320)
            return EXIT;
        // 显示充电卡界面
        else if (!isExitKey && !showWindow && x >= 75 && x <= 225 && y >= 85 && y <= 245)
            return SHOW_CHARGE_CARD;
        // 显示充值界面
        else if (showChargeCard && x >= 299 && x <= 465 && y >= 345 && y <= 389)
            return RECHARGE;
        // 显示设备信息界面
        else if (!isExitKey && !showWindow && x >= 405 && x <= 555 && y >= 265 && y <= 425)
            return SHOW_DEVICE_INFO;
        // 显示充电价格界面
        else if (!isExitKey && !showWindow && x >= 570 && x <= 720 && y >= 265 && y <= 425)
            return SHOW_CHARGING_PRICE;
        // 显示充电卡解锁界面
        else if (!isExitKey && !showWindow && x >= 240 && x <= 390 && y >= 265 && y <= 425)
            return SHOW_CHARGING_CARD_UNLOCK;
        // 充电卡解锁界面的确认键
        else if (!isExitKey && showWindow && showChargingCardUnlock && x >= 200 && x <= 323 && y >= 330 && y <= 375)
            return UNLOCK_CONFIRM;
        // 充电卡解锁界面的返回键
        else if (!isExitKey && showWindow && showChargingCardUnlock && x >= 445 && x <= 560 && y >= 330 && y <= 375)
            return UNLOCK_EXIT;
        // 显示充电账号界面
        else if (!isExitKey && !showWindow && x >= 405 && x <= 555 && y >= 85 && y <= 245)
            return SHOW_CHARGING_ACCOUNT;
        // 充电账号界面的修改密码
        else if (!isExitKey && showWindow && showChargingAccount && x >= 252 && x <= 352 && y >= 300 && y <= 340)
            return PASSWD;
        // 充电账号界面的退出登录
        else if (!isExitKey && showWindow && showChargingAccount && x >= 442 && x <= 542 && y >= 300 && y <= 340)
            return SHOWEXIT;
        // 显示充电卡查询界面
        else if (!isExitKey && !showWindow && x >= 75 && x <= 225 && y >= 265 && y <= 425)
            return SHOW_CHARGING_FIND;
        // 显示扫码充电界面
        else if (!isExitKey && !showWindow && x >= 240 && x <= 390 && y >= 85 && y <= 245)
            return SHOW_CHARGING_MODE;
        // 如果有弹窗(不包括退出弹窗),点击外面区域则表示关闭弹窗(奇怪的地方 有时候莫名其妙y=0)
        else if (!isExitKey && showWindow && !showChargingCardUnlock && !(x >= 152 && x <= 642 && y >= 88 && y <= 418) && y != 0 && x != 0)
            close_functions_window();
    }
    return UNSHOWEXIT;
}
/**
 * @brief 显示充电卡
 *
 */
void show_charge_card()
{
    showWindow = true;
    showChargeCard = true;
    show_anyjpg(152, 88, CHARGE_CARD);
    show_text(372, 42, 4, getColor(255, 183, 221, 249), 30, 50, 7, CurrentUser.ChargingCard.CardId, getColor(255, 0, 0, 0), 600, 800 * 147 + 243);
    show_text(348, 42, 4, getColor(255, 183, 221, 249), 30, 80, 7, CurrentUser.ChargingCard.Validity, getColor(255, 0, 0, 0), 600, 800 * 199 + 267);
    char money[20];
    sprintf(money, "%.2lf", CurrentUser.ChargingCard.Money);
    show_text(322, 42, 4, getColor(255, 183, 221, 249), 30, 100, 7, money, getColor(255, 255, 0, 0), 600, 800 * 251 + 293);
}
/**
 * @brief 关闭功能界面各种功能弹出的窗口
 *
 */
void close_functions_window()
{
    showWindow = false;
    showChargingCardUnlock = false;
    showChargingAccount = false;
    showChargeCard = false;
    show_anyjpg(0, 0, FUNCTIONS_IMAGE);
}
/**
 * @brief 显示设备信息
 *
 */
void show_device_info()
{
    showWindow = true;
    show_anyjpg(152, 88, DEVICE_INFO);
    show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 43, 5, CurrentDevice.DeviceId, getColor(255, 0, 0, 0), 600, 800 * 150 + 290);
    if (CurrentDevice.DeviceState)
        show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 130, 5, "空闲", getColor(255, 0, 50, 255), 600, 800 * 200 + 290);
    else
        show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 120, 5, "维护中", getColor(255, 0, 0, 255), 600, 800 * 200 + 290);
    show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 120, 5, "350kW", getColor(255, 0, 0, 0), 600, 800 * 250 + 290);
    show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 130, 5, "22kW", getColor(255, 0, 0, 0), 600, 800 * 300 + 290);
}

/**
 * @brief 通过地点获取设备信息
 *
 * @param position 设备的地点(拼音)
 * @return 包含设备信息的结构体，如果找不到设备则返回无效的结构体
 */
Device Get_Device_By_Position(TextType position)
{
    Device device = {0}; // 初始化为0，表示无效的设备
    FILE *file = fopen(DEVICE_DATA, "r");

    if (file == NULL)
    {
        printf("无法打开文件\n");
        return device;
    }

    char buffer[100];
    bool found = false;

    while (fgets(buffer, 100, file))
    {
        char tempPosition[50];
        if (sscanf(buffer, "DevicePosition: %s", tempPosition) == 1 && strcmp(tempPosition, position) == 0)
        {
            found = true;
            device.DevicePosition = strdup(tempPosition);
        }
        // 读取其他行
        if (sscanf(buffer, "DeviceId: %s", buffer) == 1)
        {
            device.DeviceId = strdup(buffer);
            continue;
        }
        if (sscanf(buffer, "DeviceType: %s", buffer) == 1)
        {
            device.DeviceType = strdup(buffer);
            continue;
        }
        if (sscanf(buffer, "DeviceState: %s", buffer) == 1)
        {
            device.DeviceState = (buffer[0] == 'T');
            continue;
        }
        if (strcmp(buffer, "----------------------------------------------------\n") == 0)
        {
            if (found)
            {
                break;
            }
            // 重置设备信息
            if (device.DeviceId)
                free(device.DeviceId);
            if (device.DeviceType)
                free(device.DeviceType);
            if (device.DevicePosition)
                free(device.DevicePosition);
            device = (Device){0};
        }
    }

    fclose(file);

    if (!found)
    {
        printf("未找到该地点的设备\n");
        if (device.DeviceId)
            free(device.DeviceId);
        if (device.DeviceType)
            free(device.DeviceType);
        if (device.DevicePosition)
            free(device.DevicePosition);
        device = (Device){0};
    }
    else
    {
        printf("找到设备: DeviceId: %s, DeviceType: %s, DeviceState: %s, DevicePosition: %s\n",
               device.DeviceId, device.DeviceType, device.DeviceState ? "True" : "False", device.DevicePosition);
    }

    return device;
}
/**
 * @brief 显示充电价格
 *
 */
void show_charging_price()
{
    showWindow = true;
    show_anyjpg(152, 88, CHARGING_PRICE);
}
/**
 * @brief 显示充电卡解锁界面
 *
 */
void show_charging_card_unlock()
{
    showWindow = true;
    showChargingCardUnlock = true;
    show_anyjpg(152, 88, CHARGING_CARD_UNLOCK);
    show_text(290, 40, 4, getColor(255, 183, 221, 249), 30, 12, 6, CurrentUser.ChargingCard.CardId, getColor(255, 0, 0, 0), 600, 800 * 151 + 240);
    show_text(230, 40, 4, getColor(255, 183, 221, 249), 32, 50, 6, CurrentUser.ChargingCard.Account, getColor(255, 0, 50, 255), 600, 800 * 201 + 300);
}
/**
 * @brief 解锁充电卡
 *
 */
void unlock_card()
{
    memset(CurrentUser.ChargingCard.CardId, 0, 21);
    generate_cardid(CurrentUser.ChargingCard.CardId);
    CurrentUser.ChargingCard.Money = 0;
    StoreData(&CurrentUser);
    CurrentUser = *(GetUserData(InputAccount));
    show_anyjpg(152, 88, UNLOCK_SUCCESS);
    show_text(290, 40, 4, getColor(255, 183, 221, 249), 30, 7, 5, CurrentUser.ChargingCard.CardId, getColor(255, 0, 0, 0), 600, 800 * 215 + 250);
    sleep(3);
}
/**
 * @brief 显示充电账号界面
 *
 */
void show_charging_account()
{
    showWindow = true;
    showChargingAccount = true;
    show_anyjpg(152, 88, CHARGING_ACCOUNT);
    show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 95, 5, CurrentUser.Account, getColor(255, 0, 50, 255), 600, 800 * 153 + 290);
    show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 30, 5, CurrentUser.ChargingCard.CardId, getColor(255, 0, 0, 0), 600, 800 * 203 + 290);
    show_text(100, 40, 4, getColor(255, 0, 50, 249), 30, 4, 5, "修改密码", getColor(255, 255, 255, 0), 600, 800 * 300 + 252);
    show_text(100, 40, 4, getColor(255, 0, 50, 249), 30, 4, 5, "退出登录", getColor(255, 255, 255, 0), 600, 800 * 300 + 442);
}
/**
 * @brief 修改密码
 *
 */
void change_password()
{
    show_anyjpg(0, 0, CHANGE_PASSWORD);
    isChangePassword = true;
    input_data();
}
/**
 * @brief 显示充值界面
 *
 */
void recharge()
{
    show_anyjpg(0, 0, RECHARGE_INTERFACE);
    InputPrice();
}
/**
 * @brief 输入充值价格
 *
 */
void InputPrice()
{
    memset(InputRechargeNum, 0, sizeof(InputRechargeNum));
    bool point = false;    // 小数点
    bool shortcut = false; // 快捷键
    while (1)
    {
        if (strlen(InputRechargeNum) == 0)
            show_text(255, 50, 4, getColor(255, 16, 136, 221), 30, 3, 10, "请输入充值金额", getColor(0, 16, 136, 128), 600, 800 * 110 + 425);
        else
            show_text(255, 50, 4, getColor(255, 16, 136, 221), 30, 3, 10, InputRechargeNum, getColor(0, 0, 0, 0), 600, 800 * 110 + 425);
        Flag event = Recharge_click(false);
        if (event == RETURN)
            return;
        else if (event == CLEAR)
        {
            memset(InputRechargeNum, 0, sizeof(InputRechargeNum));
            point = shortcut = false;
        }
        else if (event == DELETE)
        {
            if (strlen(InputRechargeNum) > 0)
            {
                shortcut = false;
                if (InputRechargeNum[strlen(InputRechargeNum) - 1] == '.')
                    point = false;
                InputRechargeNum[strlen(InputRechargeNum) - 1] = '\0';
            }
        }
        // 确认键
        else if (event == CONFIRM)
        {
            Pay(RECHARGE);
            return;
        }
        else
        {
            // 分快捷键和非快捷键
            if (event >= ZERO && event <= POINT)
            {
                // 清空快捷键留下来的数字
                if (shortcut)
                {
                    memset(InputRechargeNum, 0, sizeof(InputRechargeNum));
                    shortcut = false;
                }
                // 只能打一次小数点 或者 首位不能打小数点
                if ((point || strlen(InputRechargeNum) == 0) && event == POINT)
                    continue;
                if (!point && event == POINT)
                    point = true;
                // 将数字转成字符
                char data = keyboard_touch(event);
                sprintf(InputRechargeNum, "%s%c", InputRechargeNum, data);
            }
            else
            {
                shortcut = true;
                switch (event)
                {
                case TEN:
                    strcpy(InputRechargeNum, "10");
                    break;
                case TWENTY:
                    strcpy(InputRechargeNum, "20");
                    break;
                case FIFTY:
                    strcpy(InputRechargeNum, "50");
                    break;
                case HUNDRED:
                    strcpy(InputRechargeNum, "100");
                    break;
                default:
                    break;
                }
            }
        }
    }
}
/**
 * @brief 充值界面的点击事件
 *
 * @param BlockState 阻塞状态
 * @return Flag 点击的按键
 */
Flag Recharge_click(bool BlockState)
{
    int x = 0, y = 0;
    struct input_event input_info = {0};        // 保存触摸屏事件信息
    int fd = open("/dev/input/event0", O_RDWR); // 打开触摸屏文件
    while (1)
    {
        // 选择是否阻塞读取(阻塞的话 只能实现一个按键的点击)
        if (!BlockState)
        {
            // 设置为非阻塞 --begin--
            int status = fcntl(fd, F_GETFL);     // 1，获取当前的status 状态字
            status |= O_NONBLOCK;                // 2，将“非阻塞”属性加入status
            status = fcntl(fd, F_SETFL, status); // 3，将配置好的status 设置到fd 中
            // 设置完毕 --end--
        }

        ssize_t bytesRead = read(fd, &input_info, sizeof(input_info)); // 阻塞读取

        if (bytesRead == -1)
        {
            if (errno == EAGAIN)
                // 非阻塞读取，没有数据可读取
                continue;
            else
                break;
        }
        // 手松开
        if (EV_KEY == input_info.type && BTN_TOUCH == input_info.code && 0 == input_info.value)
        {
            printf("手松开触摸屏\n");
            // break; // 手松开退出
        }
        // 触摸屏绝对位移，x轴坐标发生改变
        if (EV_ABS == input_info.type && ABS_X == input_info.code)
        {
            x = input_info.value * 0.78125; // 保存x轴坐标(这里把显示屏x坐标优化成800)
            // x = input_info.value ;
        }
        // 触摸屏绝对位移，y轴坐标发生改变
        if (EV_ABS == input_info.type && ABS_Y == input_info.code)
        {
            y = input_info.value * 0.8; // 保存y轴坐标(这里把显示屏y坐标优化成480)
            // y = input_info.value; // 保存y轴坐标(这里把显示屏y坐标优化成480)
        }
        // printf("(%d, %d)\n", x, y);
        // 点击返回键
        if (x >= 10 && x <= 70 && y >= 10 && y <= 60)
            return RETURN;
        else if (x >= 628 && x <= 678 && y >= 175 && y <= 213)
            // 清除键
            return CLEAR;
        else if (x >= 628 && x <= 678 && y >= 230 && y <= 268)
            // 删除键
            return DELETE;
        else if (x >= 628 && x <= 678 && y >= 281 && y <= 378)
            // 确认键
            return CONFIRM;
        // 数字键的点击
        else if (x >= 425 && x <= 542 && y >= 340 && y <= 378)
            return ZERO;
        else if (x >= 425 && x <= 475 && y >= 285 && y <= 323)
            return ONE;
        else if (x >= 492 && x <= 542 && y >= 285 && y <= 323)
            return TWO;
        else if (x >= 559 && x <= 609 && y >= 285 && y <= 323)
            return THREE;
        else if (x >= 425 && x <= 475 && y >= 230 && y <= 268)
            return FOUR;
        else if (x >= 492 && x <= 542 && y >= 230 && y <= 268)
            return FIVE;
        else if (x >= 559 && x <= 609 && y >= 230 && y <= 268)
            return SIX;
        else if (x >= 425 && x <= 475 && y >= 175 && y <= 213)
            return SEVEN;
        else if (x >= 492 && x <= 542 && y >= 175 && y <= 213)
            return EIGHT;
        else if (x >= 559 && x <= 609 && y >= 175 && y <= 213)
            return NINE;
        else if (x >= 559 && x <= 609 && y >= 340 && y <= 378)
            return POINT;
        // 快捷数字键的点击
        else if (x >= 110 && x <= 194 && y >= 205 && y <= 269)
            return TEN;
        else if (x >= 264 && x <= 348 && y >= 205 && y <= 269)
            return TWENTY;
        else if (x >= 110 && x <= 194 && y >= 315 && y <= 379)
            return FIFTY;
        else if (x >= 264 && x <= 348 && y >= 315 && y <= 379)
            return HUNDRED;
    }
    return -1;
}
/**
 * @brief 选择付款方式
 *
 * @param flag 充值RECHARGE 或者 非充值!RECHARGE
 */
void Pay(Function flag)
{
    // 充电付款界面
    if (flag != RECHARGE)
    {
        show_anyjpg(152, 88, PAYWAY);
        // 选择付款方式的界面
        PaymentWay way = Pay_click(flag, false);
        if (way == NONE)
        {
            Pay(!RECHARGE);
            return;
        }
        // 选择充电卡付款
        if (way == PAY_CHARGE_CARD)
        {
            if (CurrentUser.ChargingCard.Money < atof(ChargingPrice))
            {
                show_text(310, 50, 4, getColor(255, 100, 136, 221), 30, 12, 10, "支付失败,您的充电卡余额不足", getColor(255, 255, 0, 0), 600, 800 * 138 + 245);
                sleep(2);
                Pay(!RECHARGE);
                return;
            }
            show_anyjpg(152, 88, CHARGING_AFTER);
            char paymoney[50];
            sprintf(paymoney, "应付金额: %s 元", ChargingPrice);
            show_text(490, 50, 4, getColor(255, 16, 136, 221), 32, 170, 9, paymoney, getColor(255, 255, 255, 255), 600, 800 * 88 + 152);
            show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 95, 5, CurrentUser.Account, getColor(255, 0, 50, 255), 600, 800 * 153 + 290);
            show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 30, 5, CurrentUser.ChargingCard.CardId, getColor(255, 0, 0, 0), 600, 800 * 203 + 290);
            show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 120, 5, "正常", getColor(255, 0, 0, 0), 600, 800 * 253 + 290);
            CurrentUser.ChargingCard.Money -= atof(ChargingPrice);
            char curmoney[30];
            sprintf(curmoney, "%.2lf", CurrentUser.ChargingCard.Money);
            show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 110, 5, curmoney, getColor(255, 255, 0, 0), 600, 800 * 303 + 290);
            StoreData(&CurrentUser);
            CurrentUser = *(GetUserData(InputAccount));
            sleep(2);
            show_text(130, 50, 4, getColor(255, 100, 136, 221), 30, 15, 10, "支付成功", getColor(255, 255, 0, 0), 600, 800 * 158 + 321);
            sleep(2);
            // 清空充电价钱
            memset(ChargingPrice, 0, strlen(ChargingPrice));
        }
        // 选择微信或支付宝付款
        else
        {
            show_anyjpg(152, 88, PAYWINDOW);
            char paymoney[50];
            sprintf(paymoney, "应付金额: %s 元", ChargingPrice);
            show_text(490, 50, 4, getColor(255, 16, 136, 221), 32, 140, 9, paymoney, getColor(255, 255, 255, 255), 600, 800 * 88 + 152);
            show_text(490, 40, 4, getColor(255, 100, 136, 221), 30, 160, 5, "每5秒更新一次", getColor(255, 255, 0, 0), 600, 800 * 292 + 152);
            PaymentWay paystate = forfeiture_of_payment(false);
            if (paystate == NONE)
            {
                Pay(!RECHARGE);
                return;
            }
            if (paystate == PAY_SUCCESS)
            {
                show_text(130, 50, 4, getColor(255, 100, 136, 221), 30, 15, 10, "支付成功", getColor(255, 255, 0, 0), 600, 800 * 158 + 321);
                sleep(2);
            }
        }
    }
    // 充值付款界面
    else
    {
        show_anyjpg(152, 88, PAYWAY_RECHARGE);
        // 选择付款方式的界面
        PaymentWay way = Pay_click(flag, false);
        if (way == NONE)
        {
            recharge();
            return;
        }
        // 已选付款方式的界面
        show_anyjpg(152, 88, PAYWINDOW);
        char paymoney[50];
        sprintf(paymoney, "充值金额: %s 元", InputRechargeNum);
        show_text(490, 50, 4, getColor(255, 16, 136, 221), 32, 160, 9, paymoney, getColor(255, 255, 255, 255), 600, 800 * 88 + 152);
        show_text(490, 40, 4, getColor(255, 100, 136, 221), 30, 160, 5, "每5秒更新一次", getColor(255, 255, 0, 0), 600, 800 * 292 + 152);
        PaymentWay paystate = forfeiture_of_payment(false);
        if (paystate == NONE)
        {
            recharge();
            return;
        }

        if (paystate == PAY_SUCCESS)
        {
            show_text(130, 50, 4, getColor(255, 100, 136, 221), 30, 15, 10, "充值成功", getColor(255, 255, 0, 0), 600, 800 * 158 + 321);
            CurrentUser.ChargingCard.Money += atof(InputRechargeNum);
            StoreData(&CurrentUser);
            CurrentUser = *(GetUserData(InputAccount));
            sleep(2);
        }
    }
}
/**
 * @brief 付款的方式
 *
 * @param flag 充值或者非充值 RECHARGE | !RECHAGE
 * @param BlockState 阻塞状态
 * @return PaymentWay 付款方式
 */
PaymentWay Pay_click(Function flag, bool BlockState)
{
    int x = 0, y = 0;
    struct input_event input_info = {0};        // 保存触摸屏事件信息
    int fd = open("/dev/input/event0", O_RDWR); // 打开触摸屏文件
    while (1)
    {
        // 选择是否阻塞读取(阻塞的话 只能实现一个按键的点击)
        if (!BlockState)
        {
            // 设置为非阻塞 --begin--
            int status = fcntl(fd, F_GETFL);     // 1，获取当前的status 状态字
            status |= O_NONBLOCK;                // 2，将“非阻塞”属性加入status
            status = fcntl(fd, F_SETFL, status); // 3，将配置好的status 设置到fd 中
            // 设置完毕 --end--
        }

        ssize_t bytesRead = read(fd, &input_info, sizeof(input_info)); // 阻塞读取

        if (bytesRead == -1)
        {
            if (errno == EAGAIN)
                // 非阻塞读取，没有数据可读取
                continue;
            else
                break;
        }
        // 手松开
        if (EV_KEY == input_info.type && BTN_TOUCH == input_info.code && 0 == input_info.value)
        {
            printf("手松开触摸屏\n");
            // break; // 手松开退出
        }
        // 触摸屏绝对位移，x轴坐标发生改变
        if (EV_ABS == input_info.type && ABS_X == input_info.code)
        {
            x = input_info.value * 0.78125; // 保存x轴坐标(这里把显示屏x坐标优化成800)
            // x = input_info.value ;
        }
        // 触摸屏绝对位移，y轴坐标发生改变
        if (EV_ABS == input_info.type && ABS_Y == input_info.code)
        {
            y = input_info.value * 0.8; // 保存y轴坐标(这里把显示屏y坐标优化成480)
            // y = input_info.value; // 保存y轴坐标(这里把显示屏y坐标优化成480)
        }
        // printf("(%d, %d)\n", x, y);
        // 充值付款方式界面
        if (flag == RECHARGE)
        {
            if (x >= 242 && x <= 337 && y >= 190 && y <= 317)
                return PAY_WE_CHAT;
            else if (x >= 439 && x <= 534 && y >= 190 && y <= 317)
                return PAY_ALIPAY;
            else if (!(x >= 152 && x <= 642 && y >= 88 && y <= 418) && y != 0 && x != 0 || (x >= 321 && x <= 452 && y >= 336 && y <= 384))
                return NONE;
        }
        // 充电付款方式界面
        else
        {
            if (x >= 194 && x <= 288 && y >= 190 && y <= 317)
                return PAY_CHARGE_CARD;
            else if (x >= 337 && x <= 432 && y >= 190 && y <= 317)
                return PAY_WE_CHAT;
            else if (x >= 481 && x <= 574 && y >= 190 && y <= 317)
                return PAY_ALIPAY;
            else if (!(x >= 152 && x <= 642 && y >= 88 && y <= 418) && y != 0 && x != 0)
                return NONE;
        }
    }
    return NONE;
}
/**
 * @brief 付款界面
 *
 * @param BlockState 阻塞状态
 */
PaymentWay forfeiture_of_payment(bool BlockState)
{
    char image[20];
    int i = 0;
    int time = 0; // 计时
    int x = 0, y = 0;
    struct input_event input_info = {0};        // 保存触摸屏事件信息
    int fd = open("/dev/input/event0", O_RDWR); // 打开触摸屏文件
    while (1)
    {
        // 选择是否阻塞读取(阻塞的话 只能实现一个按键的点击)
        if (!BlockState)
        {
            // 设置为非阻塞 --begin--
            int status = fcntl(fd, F_GETFL);     // 1，获取当前的status 状态字
            status |= O_NONBLOCK;                // 2，将“非阻塞”属性加入status
            status = fcntl(fd, F_SETFL, status); // 3，将配置好的status 设置到fd 中
            // 设置完毕 --end--
        }

        ssize_t bytesRead = read(fd, &input_info, sizeof(input_info)); // 阻塞读取

        if (bytesRead == -1)
        {
            if (errno == EAGAIN)
            {
                // 每三秒显示图片
                // 显示7秒后自动成功
                sprintf(image, "../Image/%d.jpg", i);
                show_anyjpg(321, 158, image);
                sleep(1);
                time++;
                if (time % 3 == 0)
                    i++;
                if ((i + 1) % 3 == 0)
                    i = 0;
                if (time == 8)
                    return PAY_SUCCESS;
                // 非阻塞读取，没有数据可读取
                continue;
            }
            else
                break;
        }
        // 手松开
        if (EV_KEY == input_info.type && BTN_TOUCH == input_info.code && 0 == input_info.value)
        {
            printf("手松开触摸屏\n");
            // break; // 手松开退出
        }
        // 触摸屏绝对位移，x轴坐标发生改变
        if (EV_ABS == input_info.type && ABS_X == input_info.code)
        {
            x = input_info.value * 0.78125; // 保存x轴坐标(这里把显示屏x坐标优化成800)
            // x = input_info.value ;
        }
        // 触摸屏绝对位移，y轴坐标发生改变
        if (EV_ABS == input_info.type && ABS_Y == input_info.code)
        {
            y = input_info.value * 0.8; // 保存y轴坐标(这里把显示屏y坐标优化成480)
            // y = input_info.value; // 保存y轴坐标(这里把显示屏y坐标优化成480)
        }
        // printf("(%d, %d)\n", x, y);
        if (x >= 321 && x <= 452 && y >= 336 && y <= 384)
            return NONE;
    }
    return NONE;
}
/**
 * @brief 显示充电卡查询界面
 *
 */
void show_charging_info()
{
    showWindow = true;
    show_anyjpg(152, 88, CHARGING_FIND);
    show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 100, 5, CurrentUser.Account, getColor(255, 0, 50, 255), 600, 800 * 153 + 290);
    show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 120, 5, "正常", getColor(255, 0, 0, 0), 600, 800 * 203 + 290);
    char money[30];
    sprintf(money, "%.2lf", CurrentUser.ChargingCard.Money);
    show_text(325, 40, 4, getColor(255, 183, 221, 249), 30, 95, 5, money, getColor(255, 255, 0, 0), 600, 800 * 253 + 290);
}
/**
 * @brief 扫码充电界面
 *
 */
void show_charge_mode()
{
    showWindow = true;
    ChargeState state = NONE;
    show_anyjpg(0, 0, CHARGE_MODE);

    state = Charge_click(state, false);
    if (state == RETURN)
        return;
    ChargeState CurMode = state;
    show_anyjpg(0, 0, STARTUPIMAGE);
    show_Charge_Start();
    show_anyjpg(0, 0, CHARGE_START);
    show_anyjpg(275, 127, CHARGE_ING);
    // 点击开始充电
    while (Charge_click(CurMode, false) != END_CHARGE)
        ;
    // 点击结束充电后跳转到付款界面
    Pay(!RECHARGE);
}
/**
 * @brief 充电界面的点击
 *
 * @param BlockState 阻塞状态
 * @return ChargeState 点击事件
 */
ChargeState Charge_click(ChargeState flag, bool BlockState)
{
    // 1表示慢充模式 2表示快充模式
    int mode;
    // 当前时间(判断是峰时还是谷时)
    char curtime[50];
    updateDateFromSystem(curtime, 50);
    double curChargeMoney;
    // 功率
    double power;
    // 充电时间的初始化
    char time_str[9];
    int seconds = 0;
    // 显示充电状态界面的标志
    bool interface = false;
    // 让开始充电后显示充电状态界面一次
    bool show_one = false;
    int x = 0, y = 0;
    struct input_event input_info = {0};        // 保存触摸屏事件信息
    int fd = open("/dev/input/event0", O_RDWR); // 打开触摸屏文件
    while (1)
    {
        // 选择是否阻塞读取(阻塞的话 只能实现一个按键的点击)
        if (!BlockState)
        {
            // 设置为非阻塞 --begin--
            int status = fcntl(fd, F_GETFL);     // 1，获取当前的status 状态字
            status |= O_NONBLOCK;                // 2，将“非阻塞”属性加入status
            status = fcntl(fd, F_SETFL, status); // 3，将配置好的status 设置到fd 中
            // 设置完毕 --end--
        }

        ssize_t bytesRead = read(fd, &input_info, sizeof(input_info)); // 阻塞读取

        if (bytesRead == -1)
        {
            if (errno == EAGAIN)
            {
                if (flag == SLOW_CHARGE)
                {
                    show_text(180, 32, 4, getColor(255, 0, 0, 0), 32, 0, 0, "慢充模式", getColor(0, 0, 255, 0), 180, 350 + 800 * 5);
                    interface = true;
                    if (check_time_period(curtime))
                        curChargeMoney = 1.5;
                    else
                        curChargeMoney = 1.0;
                    power = 220.0;
                    mode = 1;
                }
                else if (flag == FAST_CHARGE)
                {
                    show_text(180, 32, 4, getColor(255, 0, 0, 0), 32, 0, 0, "快充模式", getColor(0, 0, 255, 0), 180, 350 + 800 * 5);
                    interface = true;
                    if (check_time_period(curtime))
                        curChargeMoney = 1.8;
                    else
                        curChargeMoney = 1.2;
                    power = 350.0;
                    mode = 2;
                }
                if (interface)
                {
                    if (isCharging)
                    {
                        if (!show_one)
                        {
                            show_anyjpg(0, 0, CHARGE_END);
                            show_anyjpg(275, 127, CHARGE_ING);
                            show_one = !show_one;
                            continue;
                        }
                    }
                    // 充电功率
                    if (flag == SLOW_CHARGE)
                        show_text(150, 30, 4, getColor(255, 183, 221, 249), 30, 40, 1, "22kW", getColor(255, 0, 0, 0), 600, 800 * 156 + 370);
                    else
                        show_text(150, 30, 4, getColor(255, 183, 221, 249), 30, 35, 1, "350kW", getColor(255, 0, 0, 0), 600, 800 * 156 + 370);
                    // 充电时间
                    if (isCharging)
                        ++seconds;
                    get_elapsed_time(seconds, time_str);
                    show_text(150, 30, 4, getColor(255, 183, 221, 249), 30, 32, 1, time_str, getColor(255, 0, 50, 255), 600, 800 * 202 + 370);
                    // 充电电压
                    if (flag == SLOW_CHARGE)
                        show_text(150, 30, 4, getColor(255, 183, 221, 249), 30, 40, 1, "380V", getColor(255, 0, 0, 0), 600, 800 * 248 + 370);
                    else
                        show_text(150, 30, 4, getColor(255, 183, 221, 249), 30, 32, 1, "1000V", getColor(255, 0, 0, 0), 600, 800 * 248 + 370);
                    // 充电金额
                    char money[20];
                    // 充电功率/3600*秒数*电费
                    sprintf(money, "%.2lf", power / 3600 * seconds * curChargeMoney);
                    // 保存充电的价钱
                    sprintf(ChargingPrice, "%s", money);
                    show_text(150, 30, 4, getColor(255, 183, 221, 249), 30, 42, 1, money, getColor(255, 255, 0, 0), 600, 800 * 294 + 370);
                    usleep(800000);
                }

                // 非阻塞读取，没有数据可读取
                continue;
            }
            else
                break;
        }
        // 手松开
        if (EV_KEY == input_info.type && BTN_TOUCH == input_info.code && 0 == input_info.value)
        {
            printf("手松开触摸屏\n");
            // break; // 手松开退出
        }
        // 触摸屏绝对位移，x轴坐标发生改变
        if (EV_ABS == input_info.type && ABS_X == input_info.code)
        {
            x = input_info.value * 0.78125; // 保存x轴坐标(这里把显示屏x坐标优化成800)
            // x = input_info.value ;
        }
        // 触摸屏绝对位移，y轴坐标发生改变
        if (EV_ABS == input_info.type && ABS_Y == input_info.code)
        {
            y = input_info.value * 0.8; // 保存y轴坐标(这里把显示屏y坐标优化成480)
            // y = input_info.value; // 保存y轴坐标(这里把显示屏y坐标优化成480)
        }
        // printf("(%d, %d)\n", x, y);
        if (flag == NONE)
        {
            if (x >= 10 && x <= 70 && y >= 10 && y <= 60)
                return RETURN;
            else if (x >= 203 && x <= 343 && y >= 177 && y <= 279)
                return SLOW_CHARGE;
            else if (x >= 465 && x <= 600 && y >= 177 && y <= 279)
                return FAST_CHARGE;
        }
        else
        {
            if (!isCharging && x >= 612 && x <= 690 && y >= 359 && y <= 436)
            {
                isCharging = !isCharging;
                return START_CHARGE;
            }
            else if (isCharging && x >= 612 && x <= 690 && y >= 359 && y <= 436)
            {
                isCharging = !isCharging;
                return END_CHARGE;
            }
        }
    }
    return NONE;
}
/**
 * @brief 充电卡付款
 *
 */
void balance_payment(char money[])
{
    if (atof(money) > CurrentUser.ChargingCard.Money)
        recharge();
    else
        CurrentUser.ChargingCard.Money -= atof(money);

    StoreData(&CurrentUser);
    CurrentUser = *(GetUserData(InputAccount));
}
/**
 * @brief 微信支付宝付款
 *
 */
void WeChat_Alipay_payment(char money[])
{
    char image[20];
    for (int i = 0; i < 3; i++)
    {
        sprintf(image, "../Image/%d.jpg", i);
        show_anyjpg(321, 158, image);
        sleep(3);
    }

    show_text(130, 50, 4, getColor(255, 110, 136, 221), 30, 15, 10, "支付成功", getColor(255, 255, 0, 0), 600, 800 * 158 + 321);

    StoreData(&CurrentUser);
    CurrentUser = *(GetUserData(InputAccount));
}
/**
 * @brief 显示开始充电界面
 *
 * @param state 充电模式
 */
void show_Charge_Start()
{
    char image[30];
    // 准备充电
    for (int i = 0; i < 5; ++i)
    {
        sprintf(image, "../Image/prepare%d.jpg", i);
        show_anyjpg(275, 127, image);
        usleep(800000);
    }
}
/**
 * @brief 获得当前充电时间
 *
 * @param seconds 充电的秒数
 * @param time_str 充电字符串
 */
void get_elapsed_time(int seconds, char *time_str)
{
    int hours, minutes;

    // 计算小时、分钟和秒
    hours = seconds / 3600;
    seconds %= 3600;
    minutes = seconds / 60;
    seconds %= 60;

    // 格式化输出为 "HH:MM:SS"
    sprintf(time_str, "%02d:%02d:%02d", hours, minutes, seconds);
}
/**
 * @brief 判断时间是否在两个时间之内
 *
 * @param time_str
 * @param start_time
 * @param end_time
 * @return true
 * @return false
 */
bool is_between_time_range(const char *time_str, const char *start_time, const char *end_time)
{
    int cmp_start = compare_times(time_str, start_time);
    int cmp_end = compare_times(time_str, end_time);

    if (cmp_start >= 0 && cmp_end < 0)
    {
        return true; // 时间在 start_time 和 end_time 之间
    }
    else
    {
        return false; // 时间不在指定范围内
    }
}

/**
 * @brief 比较时间
 *
 * @param time1
 * @param time2
 * @return int
 */
int compare_times(const char *time1, const char *time2)
{
    // 提取小时、分钟、秒
    int h1, m1, s1, h2, m2, s2;
    sscanf(time1, "%2d:%2d:%2d", &h1, &m1, &s1);
    sscanf(time2, "%2d:%2d:%2d", &h2, &m2, &s2);

    // 比较小时
    if (h1 < h2)
        return -1;
    if (h1 > h2)
        return 1;

    // 比较分钟
    if (m1 < m2)
        return -1;
    if (m1 > m2)
        return 1;

    // 比较秒
    if (s1 < s2)
        return -1;
    if (s1 > s2)
        return 1;

    return 0; // 时间相等
}

/**
 * @brief 检查时间是峰时还是谷时
 *
 * @param time_str
 * @return
 * ture 峰时
 *
 * false 谷时
 */
bool check_time_period(const char *time_str)
{
    bool is_day_period = is_between_time_range(time_str, "08:00:00", "22:00:00");
    if (is_day_period)
        return true;
    else
        return false;
}